#pragma once
#include"BaseDefine.hpp"
#include<map>
#include<vector>
_NNU_UTSC_BEGIN

namespace Base{
    //类型定义
    typedef signed char        int8_t;
    typedef short              int16_t;
    typedef int                int32_t;
    typedef long long          int64_t;
    typedef unsigned char      uint8_t;
    typedef unsigned short     uint16_t;
    typedef unsigned int       uint32_t;
    typedef unsigned long long uint64_t;

    // UTSC中的数字参数

    #define M_TimeOrigin 1950                // 系统规定的时间原点

    /************************************************************************/  

    #define M_Gyr_Level 0b1010               // Gyr（十亿年）对应的level编码
    #define M_Myr_Level 0b1010               // Myr（百万年）对应的level编码
    #define M_Kyr_Level 0b1010               // Kyr（千年）对应的level编码
    #define M_Year_Level 0b1010              // Year对应的level编码
    #define M_Month_Level 0b0100             // Month对应的level编码
    #define M_Day_Level 0b0101               // Day对应的level编码
    #define M_Hour_Level 0b0101              // Hour对应的level编码
    #define M_Minute_Level 0b0110            // Minute对应的level编码
    #define M_Second_Level 0b0110            // Second对应的level编码
    #define M_Milisecond_Level 0b1010        // Milisecond对应的level编码
    #define M_Gyr_parm 0b00001010            // Gyr对应的parm编码
    #define M_Myr_parm 0b00011010            // Myr对应的parm编码
    #define M_kyr_parm 0b00101010            // Kyr对应的parm编码
    #define M_Year_parm 0b00111010           // Year对应的parm编码
    #define M_Month_parm 0b01000100          // Month对应的parm编码
    #define M_Day_parm 0b01010101            // Day对应的parm编码
    #define M_Hour_parm 0b01100101           // Hour对应的parm编码
    #define M_Minute_parm 0b01110110         // Minute对应的parm编码
    #define M_Second_parm 0b10000110         // Second对应的parm编码
    #define M_Milisecond_parm 0b10010110     // Milisecond对应的parm编码
    #define M_unknown_parm 0b00000000        // 无效parm编码

    /************************************************************************/

    #define M_Type_number 10                 // 系统时间单总数
                                                
    /************************************************************************/

    #define M_GeoTime_Max 1000               // 地质类型时间单位的最大值
    #define M_Month_Max 12                   // 月数的最大值
    #define M_Hour_Max 24                    // 小时数的最大值
    #define M_Minute_Max 60                  // 分钟数的最大值
    #define M_Second_Max 60                  // 秒数的最大值
    #define M_Milisecond_Max 1000            // 毫秒数的最大值
                                                
    #define M_GeoTime_Min 1                  // 地质类型时间的最小值
    #define M_Day_Min 1                      // 日数的最小值
    #define M_Month_Min 1                    // 月数的最小值
    #define M_Hour_Min 0                     // 小时数的最小值
    #define M_Minute_Min 0                   // 分钟数的最小值
    #define M_Second_Min 0                   // 秒数的最小值
    #define M_Milisecond_Min 0               // 毫秒数的最小值
                                                
    
    #define M_Geo_Year_Min 1948              //地质时间中年的最小值 （系统中将其当作UTC基准中的年与1950进行比较，因此这里的1948相当于1）
    #define M_Geo_Year_Max 950               //地质时间中年的最大值 （系统中将其当作UTC基准中的年与1950进行比较，因此这里的950相当于999）
    #define M_Big_Month_Days 31              // 大月的天数
    #define M_Small_Month_Days 30            // 小月的天数
    #define M_Feb_NormalYear_Days 28         // 非闰年二月天数
    #define M_Feb_LeapYear_Days 29           // 闰年二月天数

    /************************************************************************/

    #define M_LastFour_Bit 0b00001111        // 八位二进制数取后四位的掩码
    #define M_FirstFour_Bit 0b11110000       // 八位二进制数取前四位的掩码
    #define M_BitMove 4                      // 左移或右移4位所需的辅助数

    /************************************************************************/

    /// <summary>
    /// 时间单位类型
    /// </summary>
    enum class UTSCElementType
    {
        GigaYear,          // 地质时间单位：十亿年
        MegaYear,          // 地质时间单位：百万年
        KiloYear,          // 地质时间单位：千年 
        Year,              // 年
        Month,             // 月
        Day,               // 日
        Hour,              // 小时
        Minute,            // 分钟
        Second,            // 秒
        Millisecond,       // 毫秒
        Unknown            // 无效值
    };



    /// <summary>
    /// 时间基准
    /// </summary>
    enum class UTSCTimeSystemType
    {
        UTC,   // UTC标准时间，YYMMDD-HHMMSS,时间原点为1950
        Geo    // 地质时间，在年尺度表示距1950的时间，在千年尺度以上表示据今的时间
    };

    
    /// <summary>
    /// 时间拓扑关系（一个时间与另一个时间的关系）
    /// </summary>
    enum class UTSCTopoType {
        Before,         // A在B之前
        After,          // A在B之后
        StartWith,      // A和B一起开始（A比B短）
        StartBy,        // A和B一起开始（A比B长）
        FinishWith,     // A和B一起结束（A比B短）
        FinishBy,       // A和B一起结束（A比B长）
        Equal,          // A和B相等
        OverlapWith,    // A和B相交叉（A比B早）
        OverlapBy,      // A和B相交叉（A比B晚）
        Contain,        // A包含B
        ContainedBy,    // A被B包含
        MetBy,          // A和B错开（A开始，B结束）
        MeetWith,       // A和B错开（A结束，B开始）
        Unkonwn         // 无效值
    };

    /// <summary>
    /// 时间结构查询类型 （一个时间本身找关系）
    /// </summary>
    enum UTSCStructType
    {
        Parent,         // 父时间
        Children,       // 子时间
        Neighbor,       // 相邻时间
        Unkonwn,        // 无效值
    };


    /// <summary>
    /// 时间明文，存储用户输入的时间信息
    /// </summary>
    struct UTSCTime
    {
        // 单一时间片段
        struct UTSCSegmentTime
        {
            // 时间片段类型
            UTSCElementType elementType = UTSCElementType::Unknown;   
            // 时间片段值
            int data;
        };
        // 时间明文片段数
        int size = M_Type_number;
        // 时间明文片段数组
        UTSCSegmentTime *segmentTime;
        // 时间明文基准
        UTSCTimeSystemType system;
        // 时间明文构造函数
        UTSCTime(int n= M_Type_number):size(n) {
            segmentTime = new UTSCSegmentTime[size];
        }
        //时间明文析构函数
        ~UTSCTime() {
            delete[] segmentTime;  
        }

        bool setData(int i, UTSCElementType elementType, int data)
        {
            segmentTime[i].elementType = elementType;
            segmentTime[i].data = data;
            return true;
        }
        UTSCElementType getElementType(int i)
        {
            return this->segmentTime[i].elementType;
        }
        int getElementData(int i)
        {
            return this->segmentTime[i].data;
        }


    };


    /// <summary>
    /// 时间编码
    /// </summary>
    struct UTSCElementCode
    {
        // 单一时间编码片段
        struct UTSCSegmentCode
        {
            // 时间编码（base与level共八位合并成params）
            uint8_t  params = M_unknown_parm;
            // 时间编码codes码
            uint16_t codes = 0;
        };

        // 时间编码片段数
        int size = M_Type_number;
        // 时间编码数组
        UTSCSegmentCode* segmentCode = nullptr;
        // 时间编码符号码（0表示在1950之前，1表示之后）
        int8_t signal = 0;

        // 构造函数
        UTSCElementCode(int n = M_Type_number) : size(n) {
            if (size > 0) {
                segmentCode = new UTSCSegmentCode[size];
            }
        }

        // 析构函数
        ~UTSCElementCode() {
            delete[] segmentCode;
            segmentCode = nullptr;
            size = 0;
            signal = 0;
        }

        // 拷贝构造函数
        UTSCElementCode(const UTSCElementCode& other)
            : size(other.size), signal(other.signal)
        {
            if (size > 0 && other.segmentCode) {
                segmentCode = new UTSCSegmentCode[size];
                for (int i = 0; i < size; i++) {
                    segmentCode[i] = other.segmentCode[i];
                }
            }
            else {
                segmentCode = nullptr;
            }
        }

        // 拷贝赋值运算符
        UTSCElementCode& operator=(const UTSCElementCode& other)
        {
            if (this != &other) {
                delete[] segmentCode;

                size = other.size;
                signal = other.signal;

                if (size > 0 && other.segmentCode) {
                    segmentCode = new UTSCSegmentCode[size];
                    for (int i = 0; i < size; i++) {
                        segmentCode[i] = other.segmentCode[i];
                    }
                }
                else {
                    segmentCode = nullptr;
                }
            }
            return *this;
        }

        // 移动构造函数
        UTSCElementCode(UTSCElementCode&& other) noexcept
            : size(other.size), segmentCode(other.segmentCode), signal(other.signal)
        {
            other.size = 0;
            other.segmentCode = nullptr;
            other.signal = 0;
        }

        // 移动赋值运算符
        UTSCElementCode& operator=(UTSCElementCode&& other) noexcept
        {
            if (this != &other) {
                delete[] segmentCode;

                size = other.size;
                segmentCode = other.segmentCode;
                signal = other.signal;

                other.size = 0;
                other.segmentCode = nullptr;
                other.signal = 0;
            }
            return *this;
        }

        // 为python版实现的函数，用于取segmentCode数值中某个元素的params
        uint8_t getParams(int i) const
        {
            return this->segmentCode[i].params;
        }

        // 为python版实现的函数，用于取segmentCode数值中某个元素的codes
        uint16_t getCodes(int i) const
        {
            return this->segmentCode[i].codes;
        }
    };



    /// <summary>
    /// 时间单位与其对应的level码之间的映射
    /// </summary>
    static std::map<UTSCElementType, int> UTSCElementTypeMap{
        { UTSCElementType::GigaYear, M_Gyr_Level },
        { UTSCElementType::MegaYear,M_Myr_Level },
        { UTSCElementType::KiloYear,M_Kyr_Level },
        { UTSCElementType::Year,M_Year_Level },
        { UTSCElementType::Month,M_Month_Level },
        { UTSCElementType::Day,M_Day_Level },
        { UTSCElementType::Hour,M_Hour_Level },
        { UTSCElementType::Minute,M_Minute_Level },
        { UTSCElementType::Second,M_Second_Level },
        { UTSCElementType::Millisecond,M_Milisecond_Level },
    };

    // 存储UTSCElementCode数组的结构体，作为python版接口的参数
    struct TimeElementCodeStruct{
            // 默认初始化值
            int _size=0;
            UTSCElementCode *_data= nullptr;

            // 构造函数
            TimeElementCodeStruct(int size)
            {
                this->_size=size;
                _data = new UTSCElementCode[size];
            }
            // 按索引取数值中的元素
            UTSCElementCode &getDataFromIndex(int index)
            {
                if(index<this->_size) {
                    UTSCElementCode *code = &this->_data[index];
                    for (int i = 0; i < code->size; ++i) {
                        code->segmentCode[i] = this->_data[index].segmentCode[i];
                    }
                    return *code;
                }
                else
                {
                    UTSCElementCode code;
                    return code;
                }
            }

            // 析构函数
            ~TimeElementCodeStruct()
            {
                if(this->_data!= nullptr)
                    delete[] this->_data;
                this->_data= nullptr;
            }
        };
}

_NNU_UTSC_END